/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.javahispano.javacup.tacticas_aceptadas.Goteck;

import java.util.Iterator;
import java.util.LinkedList;

import java.util.Vector;
import org.javahispano.javacup.modelo.Comando;
import org.javahispano.javacup.modelo.ComandoGolpearBalon;
import org.javahispano.javacup.modelo.ComandoIrA;
import org.javahispano.javacup.modelo.Constantes;
import org.javahispano.javacup.modelo.Posicion;
import org.javahispano.javacup.modelo.SituacionPartido;

/**
 *
 * @author Administrador
 */
public class Acciones {

    static int ListaIt[] = new int[11];
    static Balon balon;
    static Posicion JugOptimoPos2 = new Posicion(0, 0);
    static public int JugOptimo2 = -1;
    static Posicion JugOptimoPos = new Posicion(0, 0);
    static public int JugOptimo = -1;

    static void setBalon(Balon pbalon, SituacionPartido sp) {
        balon = pbalon;
        if (balon.cambio) {
            Acciones.CalcJugOpt(sp);

        }



    }

    static public LinkedList<Comando> Tirar(LinkedList<Comando> comandos, SituacionPartido sp) {

        if (TacticaMonsters.JugPase == Estado_Jugada.La_tengo) {
            TacticaMonsters.JugPase = Estado_Jugada.Tirando;
        }
        Posicion portero = sp.rivales()[TacticaMonsters.PorteroRival];
        Posicion posAPasar;
        double adelantado = 52.5 - portero.getY();
        double hacialado = portero.getX();
        posAPasar = Constantes.centroArcoSup;
        for (int i = 0; i < sp.puedenRematar().length; i++) {

            Tiro t = Acciones.CalcMejorTiro(sp.detalleMisJugadores()[sp.puedenRematar()[i]].getRemate(), sp.balon().distancia(posAPasar));
            if (t.dist + 5 < adelantado) {
                comandos.add(new ComandoGolpearBalon(sp.puedenRematar()[i], posAPasar, t.fuerza, t.angVertical));
            } else {


                Posicion posteIzk = Constantes.posteIzqArcoSup;
                posteIzk.moverPosicion(0, 0.1);
                double error = (30 - 20 * sp.detalleMisJugadores()[sp.puedenRematar()[i]].getPresicion()) * 1.8 / 2;
                double angulo = Math.toDegrees(sp.misJugadores()[sp.puedenRematar()[i]].angulo(posteIzk)) - error;
                Balon b = Acciones.balon.obtBalonSimTiro(sp.detalleMisJugadores()[sp.puedenRematar()[i]].getRemate(), 1, 10, angulo);
                if (b.destinoBalon(sp).equals("fuera")) {

                    comandos.add(new ComandoGolpearBalon(sp.puedenRematar()[i], angulo, 1, 10));
                } else {
                    Posicion posteDer = Constantes.posteDerArcoSup;
                    posteDer.moverPosicion(0, -0.1);
                    error = (30 - 20 * sp.detalleMisJugadores()[sp.puedenRematar()[i]].getPresicion()) * 1.8 / 2;
                    double angulo2 = Math.toDegrees(sp.misJugadores()[sp.puedenRematar()[i]].angulo(posteDer)) + error;
                    b = Acciones.balon.obtBalonSimTiro(sp.detalleMisJugadores()[sp.puedenRematar()[i]].getRemate(), 1, 10, angulo2);
                    if (b.destinoBalon(sp).equals("fuera")) {
                        //System.out.println("GOL!");
                        comandos.add(new ComandoGolpearBalon(sp.puedenRematar()[i], angulo2, 1, 10));
                    } else {
                        if (hacialado > 0) {
                            comandos.add(new ComandoGolpearBalon(sp.puedenRematar()[i], angulo, 1, 10));
                        } else {
                            comandos.add(new ComandoGolpearBalon(sp.puedenRematar()[i], angulo2, 1, 10));
                        }
                    }
                }
            }
        }
        return comandos;
    }

    static public LinkedList<Comando> Pasar(LinkedList<Comando> comandos, int jugador, SituacionPartido sp) {

        if (TacticaMonsters.JugPase == Estado_Jugada.La_tengo) {
            TacticaMonsters.JugPase = Estado_Jugada.Pasando;
        }
        Tiro t = TacticaMonsters.paseTiro;
        Posicion posAPasar;
        posAPasar = sp.misJugadores()[jugador];
        for (int i = 0; i < sp.puedenRematar().length; i++) {
            if (sp.puedenRematar()[i] != 0) {
                comandos.add(new ComandoGolpearBalon(sp.puedenRematar()[i], posAPasar, t.fuerza, t.angVertical));
            } else {
                comandos.add(new ComandoGolpearBalon(sp.puedenRematar()[i], posAPasar, 1, 45));
            }

        /*
        Tiro t=Acciones.CalcMejorPase(sp.detalleMisJugadores()[sp.puedenRematar()[i]].getRemate(), sp.balon().distancia(posAPasar));
        double fuerzaJug=sp.detalleMisJugadores()[sp.puedenRematar()[i]].getRemate();
        double angulo=sp.balon().angulo(posAPasar);
        double fuerzaLanz=t.fuerza;
        double angVertical=t.angVertical;
        Balon b=Acciones.balon.obtBalonSimTiro(fuerzaJug, t.fuerza, t.angVertical,angulo);
        if (b.destinoBalon(sp).equals("mia")){
        comandos.add(new ComandoGolpearBalon(sp.puedenRematar()[i], posAPasar, t.fuerza, t.angVertical));
        //System.out.println("pase original bueno");
        }
        else{
        b=Acciones.balon.obtBalonSimTiro(fuerzaJug, 1, 15,angulo);
        if (b.destinoBalon(sp).equals("mia")){
        comandos.add(new ComandoGolpearBalon(sp.puedenRematar()[i], posAPasar, 1, 15));
        //System.out.println("por abajo");
        }
        else{


        int valMejor=-10000;
        Posicion mejorPos=null;
        double dist1=7;
        double dist2=14;
        for (int j=0;j<360;j=j+15){
        Posicion posNueva=new Posicion(sp.misJugadores()[jugador].getX()+Math.cos(Math.toRadians(j))*dist1,
        sp.misJugadores()[jugador].getY()+Math.sin(Math.toRadians(j))*dist1 );
        if(Math.abs(posNueva.getX())<Constantes.ANCHO_CAMPO_JUEGO/2&Math.abs(posNueva.getY())<Constantes.LARGO_CAMPO_JUEGO/2){
        Tiro t2=Acciones.CalcMejorPase(sp.detalleMisJugadores()[sp.puedenRematar()[i]].getRemate(), sp.balon().distancia(posNueva));
        b=Acciones.balon.obtBalonSimTiro(fuerzaJug, t2.fuerza, t2.angVertical,sp.balon().angulo(posNueva));
        String destino= b.destinoBalon(sp);
        //  System.out.println(destino);
        if (destino.equals("mia")){
        comandos.add(new ComandoGolpearBalon(sp.puedenRematar()[i], posNueva, t2.fuerza, t2.angVertical));
        //System.out.println("funciona");
        return comandos;
        }
        else if(j<=180){
        posNueva=new Posicion(sp.misJugadores()[jugador].getX()+Math.cos(Math.toRadians(j))*dist2,
        sp.misJugadores()[jugador].getY()+Math.sin(Math.toRadians(j))*dist2 );
        if(Math.abs(posNueva.getX())<Constantes.ANCHO_CAMPO_JUEGO/2&Math.abs(posNueva.getY())<Constantes.LARGO_CAMPO_JUEGO/2){
        t2=Acciones.CalcMejorPase(sp.detalleMisJugadores()[sp.puedenRematar()[i]].getRemate(), sp.balon().distancia(posNueva));
        b=Acciones.balon.obtBalonSimTiro(fuerzaJug, t2.fuerza, t2.angVertical,sp.balon().angulo(posNueva));
        if (b.destinoBalon(sp).equals("mia")){
        comandos.add(new ComandoGolpearBalon(sp.puedenRematar()[i], posNueva, t2.fuerza, t2.angVertical));
        System.out.println("funciona");
        return comandos;
        }

        }}}}






        comandos.add(new ComandoGolpearBalon(sp.puedenRematar()[i], posAPasar, t.fuerza, t.angVertical));//
        //System.out.println("pase original malo");




        }}}*/
        }
        return comandos;

    }

    static public LinkedList<Comando> Regatear(LinkedList<Comando> comandos, SituacionPartido sp) {

        if (TacticaMonsters.JugPase == Estado_Jugada.La_tengo) {
            TacticaMonsters.JugPase = Estado_Jugada.Regateando;
        }
        for (int i = 0; i < sp.puedenRematar().length; i++) {


            Posicion pos = Estado_Jugada.posicionLibrarse(sp, i);
            double velocidad = sp.detalleMisJugadores()[sp.puedenRematar()[i]].getVelocidad();
            double remate = sp.detalleMisJugadores()[sp.puedenRematar()[i]].getRemate();
            int iteraciones = Constantes.ITERACIONES_GOLPEAR_BALON;
            double dist = velocidad * iteraciones;
            double rozamiento = Constantes.FACTOR_DISMINUCION_VEL_BALON_SUELO;

            double velocidadBalon = dist / (1 + rozamiento + Math.pow(rozamiento, 2) + Math.pow(rozamiento, 3) + Math.pow(rozamiento, 4) + Math.pow(rozamiento, 5) + Math.pow(rozamiento, 6) + Math.pow(rozamiento, 7) + Math.pow(rozamiento, 8) + Math.pow(rozamiento, 9));
            double fuerza = velocidadBalon / (1.20 + 1.20 * remate);

            //comandos.add(new ComandoGolpearBalon(sp.puedenRematar()[i], pos, fuerza, 0));
            comandos.add(new ComandoGolpearBalon(sp.puedenRematar()[i]));
            comandos.add(new ComandoIrA(sp.puedenRematar()[i], pos));

        }
        return comandos;


    }

    static public LinkedList<Comando> QuedarseQuieto(LinkedList<Comando> comandos, SituacionPartido sp) {

        return comandos;
    }

    static public LinkedList<Comando> Atacar(LinkedList<Comando> comandos, SituacionPartido sp) {
        for (int i = 0; i < 11; i++) {
            //si no  tiene la bola, si no es el mejor jugador para cojerla y si no es el portero a desmarcarse
            if (i != 0 & i != Acciones.JugOptimo & i != 10) {
                Acciones.Desmarcar(comandos, sp, i);
            }
        }

        return comandos;
    }

    static public LinkedList<Comando> Desmarcar(LinkedList<Comando> comandos, SituacionPartido sp, int jug) {
        double distMax = 15;
        if (sp.misJugadores()[jug].distancia(TacticaMonsters.alineacionAct[jug]) > 15) {
            comandos.add(new ComandoIrA(jug, TacticaMonsters.alineacionAct[jug]));

        } else if (sp.balon().getY() < sp.misJugadores()[jug].getY() + 15) {//
            int valAct = Estado_Jugada.valorarPos(sp, sp.misJugadores()[jug]);
            int valMejor = -10000;
            Posicion mejorPos = null;
            for (int i = 0; i < 360; i = i + 30) {
                Posicion posNueva = new Posicion(sp.misJugadores()[jug].getX() + Math.cos(Math.toRadians(i)),
                        sp.misJugadores()[jug].getY() + Math.sin(Math.toRadians(i)));
                if (Math.abs(posNueva.getX()) < Constantes.ANCHO_CAMPO_JUEGO / 2 & Math.abs(posNueva.getY()) < Constantes.LARGO_CAMPO_JUEGO / 2) {
                    if (valMejor < Estado_Jugada.valorarPos(sp, posNueva)) {
                        valMejor = Estado_Jugada.valorarPos(sp, posNueva);
                        mejorPos = posNueva;
                    }
                }

            }
            if (valAct < valMejor) {
                comandos.add(new ComandoIrA(jug, mejorPos));
            }
        }

        return comandos;
    }

    static public LinkedList<Comando> Defender(LinkedList<Comando> comandos, SituacionPartido sp) {
        Acciones.AlBalon2(comandos, sp);
        boolean lMarcados[] = new boolean[11];
        for (int i = 0; i < 11; i++) {
            lMarcados[i] = false;
        }
        //el delantero k este libre x si akasoo

        for (int i = 1; i < 10; i++) {
            if (i != Acciones.JugOptimo & i != Acciones.JugOptimo2 &
                    sp.balon().getY() > sp.misJugadores()[i].getY()) {
                int jug = -1;
                double min = 100000;
                for (int j = 0; j < 11; j++) {
                    double dist = sp.rivales()[j].distancia(TacticaMonsters.alineacionAct[i]);
                    if (sp.rivales()[j].distancia(sp.balon()) > Constantes.DISTANCIA_CONTROL_BALON &
                            j != TacticaMonsters.PorteroRival & lMarcados[j] == false & dist < min) {
                        min = dist;
                        jug = j;
                    }

                }
                if (jug != -1) {
                    Posicion p = sp.rivales()[jug];
                    double angulo = sp.balon().angulo(p);
                    p.moverPosicion(Math.cos(angulo), Math.sin(angulo));
                    if (sp.misJugadores()[i].distancia(p) < 15) {
                        lMarcados[jug] = true;
                        comandos.add(new ComandoIrA(i, p));
                    }
                }

            }
        }



        return comandos;
    }

    static public LinkedList<Comando> AtacarDefender(LinkedList<Comando> comandos, SituacionPartido sp) {
        return comandos;
    }

    static public LinkedList<Comando> AlBalon(LinkedList<Comando> comandos, SituacionPartido sp) {
        if (JugOptimo != -1) {
            if (Math.abs(Acciones.JugOptimoPos.getX()) < Constantes.ANCHO_CAMPO_JUEGO + 2 / 2 & Math.abs(Acciones.JugOptimoPos.getY()) < Constantes.LARGO_CAMPO_JUEGO + 2 / 2) {
                comandos.add(new ComandoIrA(Acciones.JugOptimo, Acciones.JugOptimoPos));
            }
        }
        return comandos;
    }

    static public LinkedList<Comando> AlBalon2(LinkedList<Comando> comandos, SituacionPartido sp) {
        if (JugOptimo2 != -1 & JugOptimo2 != 0) {
            if (Math.abs(Acciones.JugOptimoPos2.getX()) < Constantes.ANCHO_CAMPO_JUEGO + 2 / 2 & Math.abs(Acciones.JugOptimoPos2.getY()) < Constantes.LARGO_CAMPO_JUEGO + 2 / 2) {
                comandos.add(new ComandoIrA(Acciones.JugOptimo2, Acciones.JugOptimoPos2));
            }
        }
        return comandos;
    }

    static void CalcJugOpt(SituacionPartido sp) {

        int numR = Integer.MAX_VALUE;
        for (int i = 0; i < 11; i++) {
            ListaIt[i] = balon.obtItParaBalon(sp, i, false);
            int nAux = balon.obtItParaBalon(sp, i, true);
            if (nAux < numR) {
                numR = nAux;
            }

        }
        int num = Integer.MAX_VALUE;
        int j = -1;
        int num2 = Integer.MAX_VALUE;
        int j2 = -1;

        for (int i = 0; i < 11; i++) {
            if (ListaIt[i] <= num) {
                if (j != 0) {
                    j2 = j;
                    num2 = num;
                }
                if (i != 0 | ListaIt[i] <= numR) {
                    j = i;//
                    num = ListaIt[i];
                }
            }

        }


        Acciones.JugOptimo = j;
        Acciones.JugOptimo2 = j2;
        Balon bAux = balon.obtValonFuturo(num);
        Acciones.JugOptimoPos = new Posicion(bAux.x, bAux.y);
        bAux = balon.obtValonFuturo(num);
        Acciones.JugOptimoPos2 = new Posicion(bAux.x, bAux.y);


    }

    public static Tiro CalcMejorPase(double fuerzaJug, double distancia) {
        Tiro t = new Tiro(0.0, 0.0, 0.0);
        if (distancia < 20) {
            return new Tiro(1.0, 0.0, 0.0);
        } else {
            double angAct = 1;
            double fuerzaTiro = 1;
            boolean encontrado = false;
            double angulo = -1;
            double diferencia = Integer.MAX_VALUE;
            while (angAct <= 60) {
                for (double fuerza = 1; fuerza > 0.5; fuerza = fuerza - 0.1) {
                    double distAct = balon.obtDistPase(fuerzaJug, fuerzaTiro, angAct);

                    double diferenciaAct = distancia - distAct;
                    if (diferenciaAct < diferencia) {

                        angulo = angAct;
                        diferencia = diferenciaAct;

                    }

                    angAct++;
                }
            }
            t.angVertical = angulo;
            t.fuerza = 1;
            if (angulo == -1) {
                t.angVertical = 5;
            }
        }
        return t;
    }

    static Tiro CalcMejorTiro(double fuerzaJug, double distancia) {
        Tiro t = new Tiro(0.0, 0.0, 10000);
        if (distancia < 16) {
            double angAct = 60;
            double fuerzaTiro = -1;
            double fuerzaTiroAct = 1;

            double diferencia = Integer.MAX_VALUE;
            while (0.6 < fuerzaTiroAct) {
                double distAct = balon.obtDistTiro(fuerzaJug, fuerzaTiroAct, angAct);
                if (distAct < distancia) {
                    double diferenciaAct = distancia - distAct;
                    if (diferenciaAct < diferencia) {

                        fuerzaTiro = fuerzaTiroAct;
                        diferencia = diferenciaAct;

                    }
                }
                fuerzaTiroAct = fuerzaTiroAct - 0.02;
            }
            if (fuerzaTiro == -1) {
                t = new Tiro(1.0, 0.0, 100000);
            }
        } else {
            double angAct = 60;
            double fuerzaTiro = 1;

            double angulo = -1;
            double diferencia = Integer.MAX_VALUE;
            while (angAct >= 0) {
                double distAct = balon.obtDistTiro(fuerzaJug, fuerzaTiro, angAct);
                if (distAct < distancia) {
                    double diferenciaAct = distancia - distAct;
                    if (diferenciaAct < diferencia) {

                        angulo = angAct;
                        diferencia = diferenciaAct;

                    }
                }
                angAct--;
            }
            t.angVertical = angulo;
            t.fuerza = 1;
            t.dist = diferencia;
            if (angulo == -1) {
                t.angVertical = 0;
            }
        }
        return t;
    }

    public static class Tiro {

        double fuerza;
        double angVertical;
        double dist;

        public Tiro(double pfuerza, double pangulo, double pdis) {
            angVertical = pangulo;
            fuerza = pfuerza;
            dist = pdis;
        }
    }
}
